/*
    Project:        Home Power Control
    File:           HPCValue.h
    Author:         christian@karunamusic.at
    Date:           12.2014
    Description:    A value class for all numeric types for use with the sensors.
 */

#ifndef HPCVALUE_H
#define HPCVALUE_H

#include <string>


/** \brief A value class for all numeric types for use with the sensors.
 */
class HPCValue
{
public:
    /**< Enum with all supported numeric types. */
    typedef enum
    {
        undefined,
        Boolean,
        SignedChar,
        UnsignedChar,
        SignedInt,
        UnsignedInt,
        SignedLong,
        UnsignedLong,
        Float,
        Double
    } ValueType;

    /**< A union type to hold the different values. */
    typedef union
    {
        bool asBoolean;
        char asSignedChar;
        unsigned char asUnsignedChar;
        int asSignedInt;
        unsigned int asUnsignedInt;
        long asSignedLong;
        unsigned long asUnsignedLong;
        float asFloat;
        double asDouble;
    } Value;

    /** \brief Constructor.
     */
    HPCValue();
    /** \brief Constructor.
     *
     * \param val The value as string (char *).
     * \param vt The valuetpe.
     *
     */
    HPCValue( const char* val, ValueType vt );
    /** \brief Copy Constructor.
     *
     * \param ref The object to copy.
     *
     */
    HPCValue( HPCValue& ref );
    /** \brief Destructor.
     */
    virtual ~HPCValue();

    /**< Get the type. */
    inline ValueType Type() const
        { return m_Type; }

    /**< Get the timestamp. */
    inline std::string Timestamp() const
        { return m_Timestamp; }

    /**< Accessor operators. */
    inline operator bool() const
        { return m_Val.asBoolean; }
    inline operator char() const
        { return m_Val.asSignedChar; }
    inline operator unsigned char() const
        { return m_Val.asUnsignedChar; }
    inline operator int() const
        { return m_Val.asSignedInt; }
    inline operator unsigned int() const
        { return m_Val.asUnsignedInt; }
    inline operator long() const
        { return m_Val.asSignedLong; }
    inline operator unsigned long() const
        { return m_Val.asUnsignedLong; }
    inline operator float() const
        { return m_Val.asFloat; }
    inline operator double() const
        { return m_Val.asDouble; }
    operator std::string() const;

    /**< Assignment operators. */
    HPCValue& operator= (bool v);
    HPCValue& operator= (char v);
    HPCValue& operator= (unsigned char v);
    HPCValue& operator= (int v);
    HPCValue& operator= (unsigned int v);
    HPCValue& operator= (long v);
    HPCValue& operator= (unsigned long v);
    HPCValue& operator= (float v);
    HPCValue& operator= (double v);
    HPCValue& operator= (const std::string& v);

    /**< Copy operator. */
    HPCValue& operator= (const HPCValue& v);

    /**< Arithmetic operators. */
    inline bool operator== (const HPCValue& v) const
        { return (m_Type == v.m_Type && m_Val.asDouble == v.m_Val.asDouble); }
    inline bool operator!= (const HPCValue& v) const
        { return !(*this == v); }
    inline bool operator>  (const HPCValue& v) const
        { return (m_Val.asDouble > v.m_Val.asDouble); }
    inline bool operator>= (const HPCValue& v) const
        { return (m_Val.asDouble >= v.m_Val.asDouble); }
    inline bool operator<  (const HPCValue& v) const
        { return (m_Val.asDouble < v.m_Val.asDouble); }
    inline bool operator<= (const HPCValue& v) const
        { return (m_Val.asDouble <= v.m_Val.asDouble); }

protected:
    ValueType m_Type; /**< The type of the value. */
    Value m_Val; /**< The value. */
    std::string m_Timestamp; /**< The timestamp when the value is last set. */

    /** \brief Get the current timestamp as string for MySQL.
     *
     * \return formatted string
     *
     */
    std::string dateTime();
};

#endif // HPCVALUE_H
